<!DOCTYPE html>
<html lang="zh-CN">
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<!-- 上述3个meta标签*必须*放在最前面，任何其他内容都*必须*跟随其后！ -->
	<title>Learning PHP，MySQL，JavaScript和CSS</title>

	<!-- Bootstrap -->
	<link href="../css/bootstrap.min.css" rel="stylesheet">

	<style>
		article{
			background: -moz-linear-gradient(top, #fb0, #f50);
		}
	</style>
	<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
	<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
	<!--[if lt IE 9]>
	<script src="http://cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
	<script src="http://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
	<![endif]-->
</head>
<body>
	<article>
		<header><h1>第1章 动态Web内容介绍</h1></header>
		<p>略</p>
	</article>
	<article>
		<header><h1>第2章 安装开发服务器</h1></header>
		<p>略</p>
	</article>
	<article>
		<header><h1>第3章 关于PHP</h1></header>
		<p>把PHP和HTML的转换次数降到最低，一个文件中发生1～2次。</p>
		<p>使用PHP的heredoc结构时，可以自由使用单引号和双引号而不需转义，也可以使用变量替换，但是对象变量好像不行。</p>
		<p>PHP中的常量在使用时前面不能加变量符号$，只能用define函数定义它们。</p>
		<p>echo输出比print函数要快一点，因为它不必返会值，也因此不能作为表达式的一部分参数计算。</p>
		<p>默认情况下，在函数中创建的变量对于函数来说是局部变量，在函数外创建的变量对于函数来说是不能被访问的，只能被函数以外的代码访问。要让变量能在所有位置访问，需要使用global关键字来声明，但是尽量不要使用这种方法。</p>
		<p>不能用表达式给静态变量赋值，只能用字面量。</p>
		<p><strong>在使用超级全局变量（比如$_POST或$_GET等等）之前，要对其进行清洁处理，比如用htmlentities函数将它转换为HTML实体。因为，对使用超级全局变量得到的数据不加变形就使用的话，可能会被人利用！</strong></p>
	</article>
	<article>
		<header>
			<h1>第4章 PHP中的表达式的控制流</h1>
		</header>
		<p>true和false的大小写都是PHP的预定义常量，而且用小写形式更加稳定，因为大写的可以被重新定义。</p>
		<p>注意，在使用条件运算符OR的时候，由于PHP的简化运算，如果OR左边的表达式为true，那右边的表达式就得不到计算。</p>
	</article>
	<article>
		<header><h1>第5章 PHP函数和对象</h1></header>
		<p>PHP函数大小写是不敏感的，因此，不要试图用大小写名称来区分函数，当然，在使用的时候要保持函数名大小写一致才是好习惯。类名是大小写敏感的，不过不要使用同样的单词定义不同的类吧。</p>
		<p>可以用PHP返回一个数组实现多值返回。如果要在函数中访问外部变量，需要在外部变量名前加global关键字，尽量不要这么做。</p>
		<p>要导入文件时使用requrie或require_once而不是include或include_once，因为后者只是试图导入被请求的文件，即使没找到也会继续执行。</p>
		<p>function_exits()函数可以检查所有预定义和自定义函数是否存在。</p>
		<p>将一个对象变赋值给一个新变量时只是创建了一个新用，要创建两个不同的对象变量应当使用clone操作符。比如：$object2 = clone $object1;。</p>
		<p>PHP自己预定义的方法名以双下划下开头，自定义方法不要这样做，与对象相关的变量或方法命名应当使用波峰命名法，类名首字母应当大写。</p>
		<p>可以在类定义中用static声明静态方法和变量，那么这个方法或变量就是属于类而不是属于某个对象，调用时应当这样：ClassName::staticFunctionOrVer;。</p>
		<p>在类中可以不必声明属性，而直接使用，但这不是个好习惯。在类中声明属性时可以赋一个默认值，但是它必须是一个直接字面量，不能是函数或表达式的计算结果。类中声明常量用const关键字，使用self关键字和双冒号运算符可以引在类中引用常量。</p>
		<p>子类不会自动调用父类的构造方法，因此，子类应当显式地调用父类构造方法，重写其它方法时也是这样，只需要用parent::__construct就可以了。</p>
	</article>
	<article>
		<header><h1>第6章 PHP数组</h1></header>
		<p>对于关联数组，可以使用这样的foreach循环：foreach($array as $key => $value)。或者，使用while结合list函数：while(list($key, $value) = each($array)）;。如果在这两个循环中需要将数组指针指回第一个元素，可以使用reset()函数，比如：reset($array)。也可以使用end()函数将函数指针移向末尾。</p>
		<p>如果要将数组中的值存在变量中，可以使用extract()函数，比如exact($_GET);，就可以将用GET方法提交的变量数组存到普通变量中，建议使用extract($_GET, EXTR_PREFIX_ALL,'prefix');，这样可以为变量定义前綴，以防止用户提交一些故意的键覆盖常用变量名，而Compact()函数的作用正好与extract()相反，它是将变量组为数组，变量名就是数组键名。</p>
	</article>
	<article>
		<header><h1>第7章 实用PHP技术</h1></header>
		<p>要实现格式化输出使用printf()函数，如果只是想使用转换后的结果而不是输出，那么使用sprintf()函数。若要为给定时间创建时间戳，可以使用mktime函数，比如mktime(23,59,59,12,30,,2000);，要显示日期，使用date()函数，它的第一个参数是格式，第二个参数是时间戳。还有很多有肜的date常量，比如DATE_W3C等同，完整的常量列表可以在http://tinyurl.com/phpdates中找到。</p>
		<p>要检测日期值是否有效，使用checkdate()函数。</p>
		<p>PHP处理文件的顺序：</p>
		<ol>
			<li>打开文件，使用fopen函数，获得文件指针</li>
			<li>调用处理函数写入（用fwrite)或读取（用fread或fgets）和进行其他处理</li>
			<li>关闭文件结束工作，使用fclose函数</li>
		</ol>
		<p>用PHP删除文件只是用unlink函数将文件从系统中删除。移动文件则是用rename重命名。复制文件，使用copy函数。使用file_get_contents()函数可以一次读取文件所有内容。</p>
		<p>要将文件上传到服务器，只城选择一种特殊的编码方式即可，其余事情由浏览器处理，比如下面这个form:</p>
		<form method="post" action="upload.php" enctype="multipart/form-data">
			Select File:<input type="file" name="filename" size="10" />
			<input type="submit" value="upload" />
		</form>
		<p>而处理上传的PHP代码如下：</p>
		<pre>
			if($_FILES){		//上传文件的所有内容都在数组$_FILES中
				$name = $_FILES['filename']['name'];	//将上传文件的实际文件名存到$name变量中
				move_uploaded_file($_FILES['filename']['tmp_name'], $name);	//将文件从临时位置移到永久存储目录，要注意目录的读写权限
				echo "Upload image '$name';
		</pre>
		<p>$_FILES数组有五个元素（其中的‘file'元素表示的是表单中类形为file的input元素的name属性值），如下:</p>
		<ul>
			<li>$_FILES['file']['name'] 上传文件的原始名字</li>
			<li>$_FILES['file']['type'] 上传文件的类型，比如：image/jpeg，常见的Internet媒体类型还有：application/pdf,application/zip, audio/mpeg， audio/x-wav, image/gif, image/png, image/tiff, multipart/form-data, text/css, text/html, text/plain, text/xml, video/mpeg, video/mp4, video/quicktime。</li>
			<li>$_FILES['file']['size'] 文件的大小（字节）</li>
			<li>$_FILES['file']['tmp_name'] 存储在服务器上临时文件的名字|</li>
			<li>$_FILES['file']['error'] 上传文件导致的错误代码</li>
		</ul>
		<p>无论何种情况，对表单数据进行验证都是必须的。另外，还要注意将文件名转为全小l写或大写，以使系统能在所有系统上运行。</p>
	</article>
	<article>
		<header><h1>第8章 MySQL入门</h1></header>
		<p>如果要在命令行输入期间中止它，只需要输入\c。</p>
	</article>
	<article>
		<header><h1>第9章 掌握MySQL</h1></header>
		<p>每个表是针对某个对象设计的。将数据分开放入表中和创建主键的过程被称为规范化，其主要目的是确保每条信息在表中只出现一次。但是对于一个表中经常查询的字段就可以不要使用关联方式了，因为会降低效率。</p>
		<p>数据库设计要遵守的三个规范被称为范式：</p>
		<p>第一范式 不有有包含相同类型数据的重复列；所有列都是单值；要有一个主键来唯一标识每一行。即列（字段）之间不要有冗余定义</p>
		<p>第二范式 在满足第一范式的基础上，行之间不要有冗余记录。 </p>
		<p>第三范式 一个符合第一、二范式的数据库已经是结构良好的了。如果有非常严谨的要求，就使用第三范式，即要求数据不直接依赖于主键，即把表的内容更进一步细化，分离出更多独立概念，但第三范式往往会需要太多关联查询而降低效率</p>
		<p>对经常查询的数据尽量不要做多表查询了。</p>
		<p>事务，可以保证数据的一致性。必须使用MySQL的InnoDB存储引擎才能使用事务，在创建数据库或表的命令尾部加上ENGINE InnoDB即可。事务以begin或start transaction语句开始，之后进行的操作都是暂时的，直到收到commit命令才会生效，在commit之前，可以用rollback命令取消所有更改。</p>
		<p>explain可以用来研究如何解释发出的查询，将它放在SELECT 语句之前会将查询相关的性质和参数列出来。</p>
		<p>要备份和恢复数据的话，使用mysqldump命令(注意，它要在系统中执行，而不是MySQL中）。主要缺点是必须确保在备份时没人向表内写入任何数据，那就只好在使用它之前关闭MySQL服务器了，完成后再重启服务，也可以在备份表时先用LOCK TABLES tableName1 READ, tableName2 READ ....命令锁定表为只读，备份完成后用UNLOCK TABLES;命令解锁所有表即可。</p>
	</article>
	<article>
		<header><h1>第10章 使用PHP访问MySQL</h1></header>
		<p>在执行数据库操作时使用diw函数是很有用的，但是有点简单粗暴，可以通过定义function mysql_fatal_error($msg)函数来显示自定义的错误消息。</p>
		<p>之所以使用or连接PHP的MySQL指令，是因为此指令能返回true或false，这样仅在它返回false时才会执行or后面的语句。</p>
		<p>不要直接读提交的$_POST或$_GET数据，在读之前应当使用mysql_real_escape_string()函数将其转码。</p>
		<p>这本书写的对MySQL的操作过于陈旧了，只浏览下吧。向MySQL中添加数据最有效的方法是创建一个数组，然后用单一查询的方式插入数据。</p>
		<p>使用auto_increment属性的ID字段，在记录刚插入时可用mysql_insert_id()来获得，这样，就可方便的将id值用于程序代码中了。注意，在插入时尽量先将表锁起来，以免出现多人同时添加时的冲突。</p>
		<p>防止SQL注入的两个手段：一经常使用mysql_real_escape_string()(只有MySQL数据库被激活时才能使用）来调用MySQL，比如可以写一个这样的函数：</p>
		<pre>
			function mysql_fix_string($string){
				if(get_magic_quotes_gpc())
					$string = tripslashes($string);
				return mysql_real_escape_string($string);
			}
		</pre>
		<p>第二是使用占位符操作数据，比如在MySQL中这样操作（以下为MySQL指令，在PHP中需要使用query函数执行：</p>
		<pre>
			PREPARE statement FROM "INSERT INTO accounts VALUES(?,?);
			SET @accounts = 12345,
				@balances = 12.34;
			EXECUTE statement USING @accounts, @balances;
			DEALLOCATE PREPARE statement;
		</pre>
		<p>另外，如果需要保存用户输入的HTML代码时，应当行用htmlentities函数来将符号转义。</p>
	</article>
	<article>
		<header><h1>第11章 表单处理</h1></header>
		<p>如果发现服务器上的register_globals在可以使用应当立即请管理员禁用它，另外，为了避免变量被覆盖，就好尖初始化每一个使用的变量。</p>
		<p>使用label标记环绕表单元素，通过点击label的可见部分可使表单元素被选中。</p>
		<p>净化用户输入是必须的，再次强调，为了防止转义字符被插入到要提交给MySQL的字符串中，应该使用mysql_real_escape_string($variable)来净化变量。要消除斜线使用stripslashes($variable)，去除HTML标记使用trip_tags()，下面是两个净化输入的函数，可用于任何代码中：</p>
		<pre>
			//用于PHP脚本的变量净化
			function sanitizeString($var){
				if(get_magic_quotes_gpc())
					$var = stripslashes($var);
				$var = htmlentities($var);
				$var = trip_tags($var);
				$return $var;
			}
			//用于MySQL数据库的变量净化
			function sanitizeMySQL($var){
				$var = mysql_real_escape_string($var);
				$var = sanitizeString($var);
				return $var;
		</pre>
	</article>
	<article>
		<header><h1>第12章 Cookie、会话和身份验证</h1></header>
		<p>cookies在传输网页header信息期间被发送，在网页的实际HTML发送之前，一旦发送了HTML之后就不能再发送cookie了。如下图：<img src="images/cookies.png">。 </p>
		<p>图中的四个步骤说明如下：</p>
		<ol>
			<li>浏览器发出请求，从网站取回主页index.html。这个header包括两个内容，第一行指定文件，第二行指定主机</li>
			<li>当服务器收到上面的header信息时，将返回请求的内容。图中的第二行header内容定义了要发送的内容类型，第三行header定义了一个cookie</li>
			<li>一旦浏览器接收到cookie，那么在将来每次由服务器发出需求时它都会返回该cookie，直到期满或被删除。所以当浏览器请求新页面时，它同样会返回cookie的name及value</li>
			<li>因为cookie已经创建，当服务接收到请求并发送新页面时，它不需要重新发送cookie，只需返回所请求的页面</li>
		</ol>
		<p>只要HTML尚未转移，就可以调用setcookie函数来设置cookie:setcookie(name,value,expire,path,domain,secure,httponly);<img src="images/setcookie.jpeg" alt="参数说明" /> </p>
		<p>读取cookie只需访问$_COOKIE数组即可，比如$_COOKIE['username']。要删除cookie，必须将它重新发布一次（即除时间戳外其它参数都一样）并设置失效时间，比如setcookie('username', 'Hannah', time()-2592000,'/');这行代码将有效期设为1个月之前，这样，cookie将因失效被删除。</p>
		<p>如果$_SERVER['PHP_AUTH_USER']和$_SERVER['PHP_AUTH_PW']都存在就说明用户输入的用户名和密码已经进入到身份验证提示中。</p>
		<p>如果要使用sha1函数来保存密码，应将密码字段长度设为40,另外，可以在密码前后插入干扰字符，比如：$salt1="qm&h"; $salt2="pg!@"; $token = sha1($salt1.$password.$salt2);在比对时也插入相同字符就行了。这样，真实的密码将很难被破解。</p>
		<p>使用session也是不安全的，因为使用数据采样可以发现通过网络的会话ID，防止这些信息被发现的唯一安全可信的方法就是实现一个SSL，并且运行HTTPS页面而不是HTTP页面。当SSL不可用时，可通过IP地址来验证用户，使用$_SERVER['REMOTE_ADDR']来获得用户IP，如果两次登录IP不同即可视为不同用户，这时最好删除当前会话，要求用户重新登录。</p>
		<p>当收到一个请会话请求时，可检查会话中随意创建的专门变量，如果变量不存在，表明是一个新会话，只需执行session_regenerate_id()来改变会话ID并设置专门会话变量来保存它，为了不这么麻烦，可以<strong>在每个session开始后都执行session_regenerate_id()函数。</strong></p>
		<p>可以用以下函数强制用户使用只有cookie的会话，不使用SESSION。ini_set('session.use_only_cookies',1);这样就不需要上面说的session更改ID的技巧了。</p>
	</article>
	<article>
		<header><h1>第13章 探究JavaScript</h1></header>
		<p>用&lt;!-- …… // -->可防止不支持JavaScript的浏览器看到JavaScript代码。</p>
		<p>无论是否使用关键字var，在函数外定义的变量都是全局变量，在函数内如果不使用var显式的定义变量，也是全局变量。</p>
		<p>JavaScript是以DOM为核心来设计的，它把HTML文档部分分解成了独立的对象。</p>
		<p>在JavaScript中$有时会被用作函数名定义，取代getElementById方法，比如：</p>
		<pre>
			function $(id){
				return document.getElementById(id);
			}
		</pre>
		<p>这样，就可以执行$(id)来取得元素对象。</p>
	</article>
	<article>
		<header><h1>第14章 JavaScript中的表达式和控制流</h1></header>
		<p>JavaScript中的true/false必须小写。</p>
		<p>JavaScript独有的with语句，可以把一个对象的多个引用简化为一个引用，比如：</p>
		<pre>
			string = 'The quick brown fox jumps over the lazy dog';
			with(string){
				document.write('The string is ' + length + 'characters, ');	//此处的length会被浏览器应用到string对象上
				document.write('In upper case is:' + toUpperCase());
			}
		</pre>
		<p>事件是能被JavaScript检测到的行为，网页上的每个元素都有可以触发JavaScript函数的某些事件。</p>
		<p>onerror，可以定义在JavaScript脚本发生语法错误时的提示消息。比如：onerror = errorHandler;这样将函自定义消息写在函数中，将会在错误发生时触发。</p>
		<p>try..cache用来捕获异常。比如：没有得到所有主流浏览器支持的代码可以写在这样的块中。</p>
		<p>JavaScript没有显式类型转换，当需要转换时可使用内置函数：</p>
		<ul>
			<li>parseInt() int,integer</li>
			<li>Boolean() bool,boolean</li>
			<li>parseFloat() float,double,real</li>
			<li>String() string</li>
			<li>split() Array</li>
		</ul>
	</article>
	<article>
		<header><h1>第15章 JavaScript函数、对象和数组</h1></header>
		<p>在函数中，可以使用函数名.arguments对象来引用函数参数数组。在函数定义时可以不定义参数表。</p>
		<p>JavaScript中类定义也用function关键字，同时定义类和构造方法（见下面的代码）。可以在类定义中使用this来引用被创建的实例，也可以将方法定义写在类定义之外，只需要类中声明函数名即可。</p>
		<pre>
			function User(forename, username, password){	//这即是类定义，也是构造函数定义
				this.forename = forename;
				this.userName = username;
				this.password = password;

				this.showUser = function(){
					……
				}
			}
			//创建一个对象
			details = new User('Wolfgang', 'w.a.mozart', 'composer');
			//也可以先创建一个空对象，再赋值
			details = new User();
			details.forename = 'Wolfgang';
			details.username = 'w.a.mozart';
			detail.password = 'composer';
		</pre>
		<p>因为方法在每种情况下都下同，因此可以让新变量引用方法的单个实例，而不是为每个新变量创建一个方法的拷贝。只需要用prototype关键字，比如上面的例子中对showUser方法的定义可以是这样：</p>
		<pre>
			//将方法声明为prototype以节省空间
			User.prototype.showUser = function(){
				……
			}
		</pre>
		<p>使用prototype甚至可以为内置对象加入新的方法或属性。比如：String.prototype.nbsp = function(){...}。</p>
		<p>有两种创建数组的方式：arrayName = new Array(); arrayName = []；。要追加新的数组元素需要使用Array的push方法。关联数组的键名和值之间用冒号分开，使用大括号定义：balls = {‘golf':'golf balls'}。</p>
		<p>遍历数组用for(key in arrayName)循环，有点类似于PHP中的foreach自动遍历数组。</p>
		<p>可以用Array的concat方法，将两个数组连在一起。比如： array1.concat(array2)或者array1.concat('item3','item4')。</p>
		<p>还可使用Array的forEach()方法遍历数组（但是IE不支持），它将传递三个参数：element,index,array，使用自定义函数操作这三个参数即可，比如：array.forEach(output); function output(element,index,array){ ...}。</p>
		<p>Array的join方法可以将数组的所有值转换为字符串，并可指定分隔符(不指定的话，使用默认的逗号分隔）。比如：array.join(':');</p>
	</article>
	<article>
		<header><h1>第16章 JavaScript和PHP验证与错误处理</h1></header>
		<p>JavaScript中主要通过两种方式使用正则表达式：test和replace：</p>
		<ul>
			<li>document.write(/cats/i.test('Cats are fun. I like cats.');	// /i表示不区分大小写，这个正则表达式测试字符串中有没有cats</li>
			<li>document.write("Cats are fun. I like cats.'.replace(/cats/gi,'dogs'); // /g表示搜索，这个表示用dogs来替换字符串中的cats</li>
		</ul>
		<p>PHP中使用正则表达式的函数有：preg_match(),preg_match_all()和preg_replace()。不要相信任何提交的东西，在使用前一定要进行代码整理，即使在JavaScript中验证过了，PHP中仍要再次验证。</p>
	</article>
	<article>
		<header><h1>第17章 使用Ajax</h1></header>
		<p>Ajax的最大优点就是不用刷新就可以更新页面内容。<a href="urlpost.html" target="_blank">示例在此，点击后页面内容会更新，但不能后退。</a>因为安全原因是无法使用Ajax直接获取域外网站网内容的。JavaScript禁止跨域使用。</p>
		<p>这里介绍的Ajax内容太少了。回头看jQuery的书。</p>
	</article>
	<article>
		<header><h1>第18章 CSS简介</h1></header>
		<p>&gt;称为子选择器，它适用于定义元素的直接子元素样式，而非是空格分隔的后代选择器。</p>
		<p>+是兄弟选择器，与子选器用法一样，不过它左中两边元素的关系是前后,比如：i + b 定义的是i元素后的兄弟元素b的样式，而i>b，则定义的是i的直接子元素b的样式。</p>
		<p>[]是属性选择器，直接在里面写上属性及值就可以了，比如：[type="submit"]。</p>
		<p>在样式表的定义项后加!important表示此项不可被覆盖 。</p>
		<p>线性渐变linear-gradient()需要加浏览器前缀。有三个参数第一个参数指定渐变开始的方向。</p>
	</article>
	<article>
		<header><h1>第19章 支持CSS3和高级CSS</h1></header>
		<p>CSS3有三个运算符用于字符串匹配，将它们放在=之前就可以匹配：^以字符串开始,$以字符串结尾,*包含字符串。比如：a[href^='web']匹配href值以web开头的a元素，a[href$='web']匹配以href属性以web结尾的元素，a[href*='web']匹配href属性值中含有web的元素。</p>
		<p>box-sizing属性用于选择盒模型，比如box-sizing:border-box；表示要使用对象的总宽和总高，包括空白与边框；box-sizing:content-box;表示只获取内容的宽和高。</p>
		<p>background-clip属性指定是否需要忽视（剪裁）出现在元素边框内或空白区域内的背景，如果不想让背景出现在边框区域内，只需定义:background-clip:padding-box;，即指定背景区域的外边缘，另外两个可用值是border-box和content-box。</p>
		<p>background-origin属性用于拕说明背景图片初始位置在边框外缘的左上角，同样有上面的三个值可用。</p>
		<p>background-size属性用来设置背景图像的宽高，格式是宽在前，高在后，中间用空格分开。如果想改变其中一个尺寸让另一个自动保持相同比例，将另一个值设为auto即可。</p>
		<p>可以使用多重背景：如下：</p>
		<pre>
			.border{
				background:
					url('b1.gif') top left no-repeat,
					url('b2.gif') top right no-repeat,
					url('b3.gif') bottom left no-repeat,
					url('b4.gif') bottom right no-repeat,
					url('bb.gif') left repeat-y,
					url('bd.gif') right repeat-y;
			}
		</pre>
		<img src="images/css3example.jpeg">
		<p>box-shadow属性定义阴影，四个参数分别为水平偏移量，垂直偏移量，模糊量，颜色。比如 box-shadow:15px 15px 10px #888。</p>
		<p>border-radius定义圆角边框。当元素过大无法被父元素容纳时，CSS中可以设置overflow属性为hidden/visible/scroll/auto来确定如何处理。CSS3则可以为水平或垂直方向单独使用这些值，比如：overflow-x:hidden;overflow-y:scroll。</p>
		<p>HSL色彩，将色彩作为一个颜色环，分为0～359度，以红（纯红为0度）绿（纯绿为120度）蓝（纯蓝为240度）各120度。color:hsl(60,100%, 50%)这样定义的是一个100%饱和具有标准亮度的黄色。使用hsla(60,100%,50%,0.3);第四位是透明度。</p>
		<p>text-shadow定义文本阴影。要实现文本溢出时，在截断文本处放一个省略号代替，可以如下实现：</p>
		<ol>
			<li>定义overflow超出部分隐藏：overflow:hidden;</li>
			<li>使用white-space:nowrap来约束文本</li>
			<li>定义text-flow:ellipsis实现省略号效果</li>
		</ol>
		<p>用@font-face属性声明网页字体，提高排版的有效性。不过汉字等字体文件太大，不太适应。定义如下：</p>
		<pre>
			@font-face{
				font-family: FontName;
				src:url('FontName.otf');	//大多数浏览器支持otf和ttf字体,也可以在后面指定字体类型，比如:src:url('FontName.otf') format('opentype');
			}
		</pre>
		<p>使用网络字体最好的方式是使用免费的Google字体，http://google.com/webfonts，这儿有500多种字体族。加载时只需这样在HTML中用link标记加载一种字体：&lt;href="http://fonts.googleapis.com/css?family=Lobster" /&gt;，然后就可以在CSS代码中使用这种字体了:h1{font-family:'Lobster', arial, serif;}</p>
		<p>用transform属性可以实现旋转，移动，缩放，扭曲等效果。</p>
	</article>
	<article>
		<header><h1>第20章 由JavaScript访问CSS</h1></header>
		<p>为了防止与其它框架冲突，使用O函数代替$函数。function O(obj){if(typeof obj == 'object') return obj;else return document.getElementById(obj);}</p>
		<p>再定义一个S函数用来简化对样式表的引用：function S(obj){ return O(obj).style;}，这样就可以如此调用样式：S('id').color='green'。</p>
		<p><strong>注意：当以上两个函数需要传递 对象时，一定不能将对象名放在引号内。</strong></p>
		<p>如果要通过类来引用多个元素时，可以再定义一个C函数：</p>
		<pre>
			function C(name){
				var elements = document.getElementByTagName('*')	//获取所有元素
				var objects = []
				for(var i = 0; i < objects.length;i++){
					if(elements[i].className == name)	//将名为name的元素放在数组中
						objects.push(element[i])
				return objects;
			}
		</pre>
		<p>由于CSS中有带连字符-的属性，而JavaScript将之视为运算符，因此，这类属性在JavaScript调用时都将连字符去掉，并将其后的第一个字符大写。比如myobject.fontSize='16px';。也可以使用myobject.setAttribute('font-size','16px');。</p>
		<p>要读取浏览器窗品可以提供多大空间，可使用window.innerHeight和window.innerWidth。screen对象支持只读属性availHeight,availWidth,colorDepth,height,pixelDepth和width。</p>
		<p>也可以使用内联JavaScript，比如：&lt;img src='apple.png' onmouseover="this.src='orange.png'" onmouseout="this.src='apple.png'" /&gt;</p>
	</article>
	<article>
		<header><h1>第21章 综合应用</h1></header>
		<p>这一章讲了<a href="robinsnest/index.php">一个简单案例</a>，源代码已包括进来。</p>
	</article>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="../js/bootstrap.min.js"></script>
</body>
</html>